home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / grafik / 3d & render tools / irit / contrib / aisoshad / aisoshad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  23.7 KB  |  754 lines

  1. /*****************************************************************************
  2. * Adaptive Iso Shader program to render freeform models.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                 Ver 1.0, January 1994   *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include <string.h>
  10. #include "irit_sm.h"
  11. #include "config.h"
  12. #include "iritgrap.h"
  13. #include "attribut.h"
  14. #include "allocate.h"
  15. #include "iritgrap.h"
  16. #include "poly_cln.h"
  17. #include "geomat3d.h"
  18. #include "getarg.h"
  19. #include "ip_cnvrt.h"
  20.  
  21. typedef enum {                   /* Type of distance function computation. */
  22.     AISO_DIST_REGULAR = 0,
  23.     AISO_DIST_PHONG,
  24.     AISO_DIST_PHONG_2L,
  25.     AISO_DIST_PHONG_SPEC,
  26.     AISO_DIST_PHONG_2L_SPEC,
  27.     AISO_DIST_ZNORMAL,
  28.     AISO_DIST_POINT_E3
  29. } AIsoDistCompType;
  30.  
  31. #define NORMAL_ANGLE_SCALE    1e5
  32. #define TRUNCATED_DOMAIN    1e-3
  33. #define MIN_DOMAIN_VALID    1e-2
  34. #define MAX_LEVEL_VALID        100
  35.  
  36. #ifdef NO_CONCAT_STR
  37. static char *VersionStr =
  38.     "AIsoShad        Version 4.0,    Gershon Elber,\n\
  39.      (C) Copyright 1989/90/91/92/93 Gershon Elber, Non commercial use only.";
  40. #else
  41. static char *VersionStr =
  42.     "AIsoShad        " VERSION ",    Gershon Elber,    "
  43.     __DATE__ ",   " __TIME__ "\n" COPYRIGHT ", Non commercial use only.";
  44. #endif /* NO_CONCAT_STR */
  45.  
  46. static char *CtrlStr =
  47. #ifdef DOUBLE
  48.     "AIsoShad o%-OutName!s m%- i%- r%-RndrMdl!d c%-CosPwr!F s%-SdrPwr!F l%-Lx|Ly|Lz!F!F!F R%-Random!F d%-AdapDir!d t%-SrfZTrans!F M%-MinSubdiv!d D%-AdapDist!F w%-AdapIsoWidth!F W%- z%- DFiles!*s";
  49. #else
  50.     "AIsoShad o%-OutName!s m%- i%- r%-RndrMdl!d c%-CosPwr!f s%-SdrPwr!f l%-Lx|Ly|Lz!f!f!f R%-Random!F d%-AdapDir!d t%-SrfZTrans!f M%-MinSubdiv!d D%-AdapDist!f w%-AdapIsoWidth!f W%- z%- DFiles!*s";
  51. #endif
  52.  
  53. static char
  54.     *GlblLightSourceStr = "",
  55.     *GlblOutFileName = "aisoshad.dat";
  56.  
  57. static AIsoDistCompType
  58.     GlblDistRndrModel = AISO_DIST_PHONG;
  59.  
  60. static int
  61.     GlblSymbInterp = TRUE,
  62.     GlblAdapIsoColor = IG_IRIT_WHITE,
  63.     GlblAdapIsoDir[2] = { CAGD_CONST_U_DIR, CAGD_NO_DIR },
  64.     GlblTalkative = FALSE,
  65.     GlblMinSubdivLevel = 1,
  66.     GlblVariableWidth = FALSE;
  67.  
  68. static RealType
  69.     GlblCosinePower = 1,
  70.     GlblShaderPower = 2,
  71.     GlblLightSource[3] = { 1.0, 0.0, 0.0 },
  72.     GlblSrfTranslate[3] = { 0.0, 0.0, 0.01 },
  73.     GlblRandomDist = 1.0,
  74.     GlblAdapDistance = 1.0,
  75.     GlblAdapIsoWidth = 0.001,
  76.     GlblVarWidthSegLen = 0.1;
  77.  
  78. static ConfigStruct SetUp[] =
  79. {
  80.   { "AdapDir",        "-d", (VoidPtr) &GlblAdapIsoDir[0],   SU_INTEGER_TYPE },
  81.   { "AdapIsoColor",   "",   (VoidPtr) &GlblAdapIsoColor,    SU_INTEGER_TYPE },
  82.   { "RenderModel",    "-r", (VoidPtr) &GlblDistRndrModel,   SU_INTEGER_TYPE },
  83.   { "MinSubdiv",      "-M", (VoidPtr) &GlblMinSubdivLevel,  SU_INTEGER_TYPE },
  84.   { "SymbInterp",     "-i", (VoidPtr) &GlblSymbInterp,        SU_BOOLEAN_TYPE },
  85.   { "MoreVerbose",    "-m", (VoidPtr) &GlblTalkative,        SU_BOOLEAN_TYPE },
  86.   { "LightSrcDir",    "-l", (VoidPtr) &GlblLightSourceStr,  SU_STRING_TYPE },
  87.   { "AdapIsoWidth",   "-w", (VoidPtr) &GlblAdapIsoWidth,    SU_REAL_TYPE },
  88.   { "CosinePower",    "-c", (VoidPtr) &GlblCosinePower,     SU_REAL_TYPE },
  89.   { "ShaderPower",    "-s", (VoidPtr) &GlblShaderPower,     SU_REAL_TYPE },
  90.   { "RandomDist",     "-R", (VoidPtr) &GlblRandomDist,      SU_REAL_TYPE },
  91.   { "SrfZTrans",      "-t", (VoidPtr) &GlblSrfTranslate[2], SU_REAL_TYPE },
  92.   { "AdapDistance",   "-D", (VoidPtr) &GlblAdapDistance,    SU_REAL_TYPE },
  93. };
  94. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  95.  
  96. static CagdCrvStruct *AdapIsoDistSqr(int Level,
  97.                      CagdCrvStruct *Crv1,
  98.                      CagdCrvStruct *NCrv1,
  99.                      CagdCrvStruct *Crv2,
  100.                      CagdCrvStruct *NCrv2);
  101. static RealType IntPower2(RealType t, int Power);
  102. static void AIsoShaderExit(int ExitCode);
  103.  
  104. /*****************************************************************************
  105. * DESCRIPTION:                                                               M
  106. * Main module of AIsoShad - Read command line and do what is needed...         M
  107. *                                                                            *
  108. * PARAMETERS:                                                                M
  109. *   argc, argv:  Command line.                                               M
  110. *                                                                            *
  111. * RETURN VALUE:                                                              M
  112. *   void                                                                     M
  113. *                                                                            *
  114. * KEYWORDS:                                                                  M
  115. *   main                                                                     M
  116. *****************************************************************************/
  117. void main(int argc, char **argv)
  118. {
  119.     int Error,
  120.     DistCompFlag = FALSE,
  121.     CosinePowerFlag = FALSE,
  122.     ShaderPowerFlag = FALSE,
  123.     AdapDirFlag = FALSE,
  124.     SrfZTransFlag = FALSE,
  125.     AdapDistanceFlag = FALSE,
  126.     AdapIsoWidthFlag = FALSE,
  127.         LightSrcFlag = FALSE,
  128.         MinSubdivFlag = FALSE,
  129.     RandomFlag = FALSE,
  130.     OutFileFlag = FALSE,
  131.     VerFlag = FALSE,
  132.     NumFiles = 0;
  133.     char
  134.     **FileNames = NULL;
  135.     FILE *f;
  136.     IPObjectStruct *PObjects, *NoProcessObjs, *PObj,
  137.     *PObjWaves = NULL;
  138.     MatrixType CrntViewMat;
  139.  
  140.     Config("aisoshad", SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  141.     if (GlblLightSourceStr != NULL && strlen(GlblLightSourceStr) > 0) {
  142. #ifdef DOUBLE
  143.     if (sscanf(GlblLightSourceStr, "%lf,%lf,%lf",
  144. #else
  145.     if (sscanf(GlblLightSourceStr, "%f,%f,%f",
  146. #endif /* DOUBLE */
  147.            &GlblLightSource[0],
  148.            &GlblLightSource[1],
  149.            &GlblLightSource[2]) != 3) {
  150.         fprintf(stderr,
  151.             "Fail to parse LightSrcDir in configuration file.\n");
  152.         AIsoShaderExit(-1);
  153.     }
  154.     }
  155.  
  156.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  157.                &OutFileFlag, &GlblOutFileName, &GlblTalkative,
  158.                &GlblSymbInterp, &DistCompFlag, &GlblDistRndrModel,
  159.                &CosinePowerFlag, &GlblCosinePower,
  160.                &ShaderPowerFlag, &GlblShaderPower,
  161.                &LightSrcFlag, &GlblLightSource[0],
  162.                &GlblLightSource[1], &GlblLightSource[2],
  163.                &RandomFlag, &GlblRandomDist,
  164.                &AdapDirFlag, &GlblAdapIsoDir[0],
  165.                &SrfZTransFlag, &GlblSrfTranslate[2],
  166.                &MinSubdivFlag, &GlblMinSubdivLevel,
  167.                &AdapDistanceFlag, &GlblAdapDistance,
  168.                &AdapIsoWidthFlag, &GlblAdapIsoWidth,
  169.                &GlblVariableWidth,
  170.                &VerFlag, &NumFiles, &FileNames)) != 0) {
  171.     GAPrintErrMsg(Error);
  172.     GAPrintHowTo(CtrlStr);
  173.     AIsoShaderExit(1);
  174.     }
  175.  
  176.     if (VerFlag) {
  177.     fprintf(stderr, "\n%s\n\n", VersionStr);
  178.     GAPrintHowTo(CtrlStr);
  179.     ConfigPrint(SetUp, NUM_SET_UP);
  180.     AIsoShaderExit(0);
  181.     }
  182.  
  183.     if (!NumFiles) {
  184.     fprintf(stderr, "No data file names where given, exit.\n");
  185.     GAPrintHowTo(CtrlStr);
  186.     AIsoShaderExit(1);
  187.     }
  188.  
  189.     switch (GlblAdapIsoDir[0]) {
  190.         case 0:
  191.         GlblAdapIsoDir[0] = CAGD_CONST_U_DIR;
  192.         break;
  193.     case 1:
  194.         GlblAdapIsoDir[0] = CAGD_CONST_V_DIR;
  195.         break;
  196.     case 2:
  197.         GlblAdapIsoDir[0] = CAGD_CONST_U_DIR;
  198.         GlblAdapIsoDir[1] = CAGD_CONST_V_DIR;
  199.         break;
  200.     default:
  201.         break;
  202.     }
  203.  
  204.     BspMultInterpFlag(GlblSymbInterp);
  205.     SymbSetAdapIsoExtractMinLevel(GlblMinSubdivLevel);
  206.  
  207.     if (GlblDistRndrModel != AISO_DIST_POINT_E3)
  208.     PT_NORMALIZE(GlblLightSource);
  209.  
  210.     if (GlblRandomDist < 1) {
  211.     fprintf(stderr,    "Randomization [-R] should not be less than one\n");
  212.     AIsoShaderExit(0);
  213.     }
  214.  
  215.     /* Get the data files: */
  216.     if ((PObjects = IritPrsrGetDataFiles(FileNames, NumFiles, TRUE, FALSE)) ==
  217.                                     NULL)
  218.     AIsoShaderExit(0);
  219.  
  220.     if (IritPrsrWasPrspMat)
  221.     MatMultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  222.     else
  223.     GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
  224.  
  225.     PObj = GMTransformObjectList(PObjects, CrntViewMat);
  226.     IPFreeObjectList(PObjects);
  227.     PObjects = PObj;
  228.  
  229.     /* Open output file, if necessary. */
  230.     if (OutFileFlag) {
  231.     if ((f = fopen(GlblOutFileName, "w")) == NULL) {
  232.         fprintf(stderr, "Failed to open \"%s\".\n", GlblOutFileName);
  233.         AIsoShaderExit(2);
  234.     }
  235.     }
  236.     else
  237.     f = stdout;
  238.  
  239.     /* Traverse all the objects and generate the coverage for them. */
  240.     for (PObj = PObjects; PObj != NULL; PObj = PObj -> Pnext) {
  241.     if (GlblTalkative)
  242.         fprintf(stderr, "Processing object \"%s\"\n", PObj -> Name);
  243.  
  244.     if (IP_IS_SRF_OBJ(PObj)) {
  245.         CagdSrfStruct *Srf;
  246.         int SrfAdapIsoDir[2],
  247.         SrfAdapIsoMinSubdiv = AttrGetObjectIntAttrib(PObj,
  248.                               "AdapIsoMinSubdiv");
  249.         RealType
  250.         RelativeAdapIsoDist = AttrGetObjectRealAttrib(PObj,
  251.                                   "AdapIsoDist");
  252.  
  253.         if (RelativeAdapIsoDist > IP_ATTR_BAD_REAL / 10.0)
  254.         RelativeAdapIsoDist = 1.0;
  255.  
  256.         SrfAdapIsoDir[0] = AttrGetObjectIntAttrib(PObj, "AdapIsoDir");
  257.         switch (SrfAdapIsoDir[0]) {
  258.         case 0:
  259.             SrfAdapIsoDir[0] = CAGD_CONST_U_DIR;
  260.             break;
  261.         case 1:
  262.             SrfAdapIsoDir[0] = CAGD_CONST_V_DIR;
  263.             break;
  264.         case 2:
  265.             SrfAdapIsoDir[0] = CAGD_CONST_U_DIR;
  266.             SrfAdapIsoDir[1] = CAGD_CONST_V_DIR;
  267.             break;
  268.         default:
  269.             SrfAdapIsoDir[0] = GlblAdapIsoDir[0];
  270.             SrfAdapIsoDir[1] = GlblAdapIsoDir[1];
  271.             break;
  272.         }
  273.  
  274.         if (SrfAdapIsoMinSubdiv != IP_ATTR_BAD_INT)
  275.             SymbSetAdapIsoExtractMinLevel(SrfAdapIsoMinSubdiv);
  276.  
  277.         /* Set the color of the surfaces to black. */
  278.         AttrSetObjectColor(PObj, IG_IRIT_BLACK);
  279.         AttrSetObjectRGBColor(PObj, 0, 0, 0);
  280.  
  281.         IritPrsrPutObjectToFile(f, PObj);  /* Dump it as is. */
  282.  
  283.         for (Srf = PObj -> U.Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  284.         RealType UMin, UMax, VMin, VMax;
  285.         IPObjectStruct *PAdapIsoObj;
  286.         CagdSrfStruct *TSrf, *TSrf1,
  287.             *NSrf = SymbSrfNormalSrf(Srf);
  288.         CagdCrvStruct *Crv, *AdapIso;
  289.  
  290.         /* Remove a little from all four boundaries to prevent from */
  291.         /* dealing with degenerated cases so common on boundary.    */
  292.         CagdSrfDomain(Srf, &UMin, &UMax, &VMin, &VMax);
  293.         TSrf1 = CagdSrfRegionFromSrf(Srf,
  294.                          UMin + TRUNCATED_DOMAIN,
  295.                          UMax - TRUNCATED_DOMAIN,
  296.                          CAGD_CONST_U_DIR);
  297.         TSrf = CagdSrfRegionFromSrf(TSrf1,
  298.                         VMin + TRUNCATED_DOMAIN,
  299.                         VMax - TRUNCATED_DOMAIN,
  300.                         CAGD_CONST_V_DIR);
  301.                          
  302.         CagdSrfFree(TSrf1);
  303.  
  304.         CagdSrfTransform(TSrf, GlblSrfTranslate, 1.0);
  305.         AdapIso = SymbAdapIsoExtract(TSrf, NSrf, AdapIsoDistSqr,
  306.                          SrfAdapIsoDir[0],
  307.                          GlblAdapDistance *
  308.                              RelativeAdapIsoDist,
  309.                          FALSE, FALSE);
  310.         if (SrfAdapIsoDir[1] != CAGD_NO_DIR) {
  311.             CagdCrvStruct *AdapIsoLast,
  312.                 *AdapIso2 = SymbAdapIsoExtract(TSrf, NSrf,
  313.                                AdapIsoDistSqr,
  314.                                SrfAdapIsoDir[1],
  315.                                GlblAdapDistance *
  316.                                   RelativeAdapIsoDist,
  317.                                FALSE, FALSE);
  318.  
  319.             if (AdapIso != NULL) {
  320.                 AdapIsoLast = CagdListLast(AdapIso);
  321.  
  322.             AdapIsoLast -> Pnext = AdapIso2;
  323.             }
  324.             else
  325.                 AdapIso = AdapIso2;
  326.         }
  327.  
  328.         CagdSrfFree(NSrf);
  329.         CagdSrfFree(TSrf);
  330.  
  331.         /* Remove the normal curves from the list. */
  332.         for (Crv = AdapIso; Crv != NULL; Crv = Crv -> Pnext) {
  333.             CagdCrvStruct
  334.             *NextCrv = Crv -> Pnext -> Pnext;
  335.  
  336.             Crv -> Pnext -> Pnext = NULL;
  337.             CagdCrvFree(Crv -> Pnext);
  338.             Crv -> Pnext = NextCrv;
  339.         }
  340.  
  341.         if (GlblVariableWidth) {
  342.             /* Save every curve with its variable width function. */
  343.             for (Crv = AdapIso; Crv != NULL; ) {
  344.             CagdCrvStruct
  345.                 *NextCrv = Crv -> Pnext;
  346.  
  347.             Crv -> Pnext = NULL;
  348.  
  349.             PAdapIsoObj = GenCRVObject(Crv);
  350.             PAdapIsoObj -> Attrs = Crv -> Attr;
  351.             Crv -> Attr = NULL;
  352.             AttrSetObjectColor(PAdapIsoObj, GlblAdapIsoColor);
  353.  
  354.             IritPrsrPutObjectToFile(f, PAdapIsoObj);
  355.             IPFreeObject(PAdapIsoObj);
  356.  
  357.             Crv = NextCrv;
  358.             }
  359.         }
  360.         else {
  361.             PAdapIsoObj = GenCRVObject(AdapIso);
  362.             AttrSetObjectColor(PAdapIsoObj, GlblAdapIsoColor);
  363.             AttrSetObjectRealAttrib(PAdapIsoObj, "width",
  364.                         GlblAdapIsoWidth);
  365.  
  366.             IritPrsrPutObjectToFile(f, PAdapIsoObj);
  367.             IPFreeObject(PAdapIsoObj);
  368.         }
  369.         }
  370.  
  371.         SymbSetAdapIsoExtractMinLevel(GlblMinSubdivLevel);
  372.     }
  373.     }
  374.  
  375.     AIsoShaderExit(0);
  376. }
  377.  
  378. /*****************************************************************************
  379. * DESCRIPTION:                                                               *
  380. *   Computes a distance square function between Crv1 and Crv2 as a scalar    *
  381. * field. The normal vector fields (not unit size) of the two curves are also *
  382. * provided as NCrv1, NCrv2.                             *
  383. *                                                                            *
  384. * PARAMETERS:                                                                *
  385. *   Level:     Maximum depth of recursion of adaptive iso algorithm.         *
  386. *   Crv1:      First curve to compute distance field from it to Crv2.        *
  387. *   NCrv1:     Normal vector field of Crv1.                                  *
  388. *   Crv2:      Second curve to compute distance field from it to Crv1.       *
  389. *   NCrv2:     Normal vector field of Crv2.                                  *
  390. *                                                                            *
  391. * RETURN VALUE:                                                              *
  392. *   CagdCrvStruct *:  A scalar distance function field.                      *
  393. *****************************************************************************/
  394. static CagdCrvStruct *AdapIsoDistSqr(int Level,
  395.                      CagdCrvStruct *Crv1,
  396.                      CagdCrvStruct *NCrv1,
  397.                      CagdCrvStruct *Crv2,
  398.                      CagdCrvStruct *NCrv2)
  399. {
  400.     int i;
  401.     CagdRType TMin, TMax, *Points1, *Points2;
  402.     CagdCrvStruct
  403.     *DistCrv2Aux1 = NULL,
  404.     *DistCrv2Aux2 = NULL,
  405.         *DiffCrv = SymbCrvSub(Crv1, Crv2),
  406.         *DiffCrv2D = CagdCoerceCrvTo(DiffCrv, CAGD_PT_E2_TYPE),
  407.         *DistCrv2 = SymbCrvDotProd(DiffCrv2D, DiffCrv);
  408.  
  409.     CagdCrvFree(DiffCrv);
  410.     CagdCrvFree(DiffCrv2D);
  411.  
  412.     CagdCrvDomain(Crv1, &TMin, &TMax);
  413.  
  414.     if (GlblVariableWidth) {
  415.     if (DistCrv2 -> PType != CAGD_PT_E1_TYPE)
  416.         DistCrv2Aux1 = CagdCoerceCrvTo(DistCrv2, CAGD_PT_E1_TYPE);
  417.     else
  418.         DistCrv2Aux1 = CagdCrvCopy(DistCrv2);
  419.     DistCrv2Aux2 = CagdCrvCopy(DistCrv2Aux1);
  420.  
  421.     Points1 = DistCrv2Aux1 -> Points[1];
  422.     Points2 = DistCrv2Aux2 -> Points[1];
  423.     }
  424.  
  425.     if (TMax - TMin > MIN_DOMAIN_VALID && Level < MAX_LEVEL_VALID) {
  426.     CagdRType TMin1, TMax1, TMin2, TMax2,
  427.         *Points = DistCrv2 -> Points[1],
  428.         *Nodes = CagdCrvNodes(DistCrv2);
  429.  
  430.     CagdCrvDomain(NCrv1, &TMin1, &TMax1);
  431.     CagdCrvDomain(NCrv2, &TMin2, &TMax2);
  432.  
  433.     switch (GlblDistRndrModel) {
  434.         case AISO_DIST_PHONG:
  435.         case AISO_DIST_PHONG_2L:
  436.         case AISO_DIST_PHONG_SPEC:
  437.         case AISO_DIST_PHONG_2L_SPEC:
  438.             for (i = 0; i < DistCrv2 -> Length; i++) {
  439.             CagdVType N1, N2, RefDir;
  440.             CagdRType *R, Z, Z1, Z2,
  441.                 t1 = BOUND(Nodes[i], TMin1, TMax1),
  442.                 t2 = BOUND(Nodes[i], TMin2, TMax2);
  443.  
  444.             R = CagdCrvEval(NCrv1, t1);
  445.             CagdCoerceToE3(N1, &R, -1, NCrv1 -> PType);
  446.             R = CagdCrvEval(NCrv2, t2);
  447.             CagdCoerceToE3(N2, &R, -1, NCrv2 -> PType);
  448.  
  449.             PT_NORMALIZE(N1);
  450.             PT_NORMALIZE(N2);
  451.  
  452.             if (GlblVariableWidth) {
  453.             if (GlblDistRndrModel == AISO_DIST_PHONG_2L ||
  454.                 GlblDistRndrModel == AISO_DIST_PHONG_2L_SPEC) {
  455.                 Z1 = fabs(DOT_PROD(N1, GlblLightSource));
  456.                 Z2 = fabs(DOT_PROD(N2, GlblLightSource));
  457.  
  458.                 if (GlblDistRndrModel == AISO_DIST_PHONG_2L_SPEC) {
  459.                 /* Add specular term, if have one. */
  460.                 if (DOT_PROD(N1, GlblLightSource) > 0.0) {
  461.                     PT_COPY(RefDir, N1);
  462.                     PT_SCALE(RefDir, 2 * Z);
  463.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  464.                     Z1 += pow(fabs(RefDir[2]),
  465.                           GlblCosinePower);
  466.                 }
  467.                 else {
  468.                     PT_COPY(RefDir, N1);
  469.                     PT_SCALE(RefDir, -2 * Z);
  470.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  471.                     Z1 += pow(fabs(RefDir[2]),
  472.                           GlblCosinePower);
  473.                 }
  474.  
  475.                 if (DOT_PROD(N2, GlblLightSource) > 0.0) {
  476.                     PT_COPY(RefDir, N2);
  477.                     PT_SCALE(RefDir, 2 * Z);
  478.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  479.                     Z2 += pow(fabs(RefDir[2]),
  480.                           GlblCosinePower);
  481.                 }
  482.                 else {
  483.                     PT_COPY(RefDir, N2);
  484.                     PT_SCALE(RefDir, -2 * Z);
  485.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  486.                     Z2 += pow(fabs(RefDir[2]),
  487.                           GlblCosinePower);
  488.                 }
  489.                 }
  490.             }
  491.             else { /* AISO_DIST_PHONG || AISO_DIST_PHONG_SPEC */
  492.                 Z1 = (DOT_PROD(N1, GlblLightSource));
  493.                 Z1 = (Z1 + 1.0) / 2.0;
  494.                 Z2 = (DOT_PROD(N2, GlblLightSource));
  495.                 Z2 = (Z2 + 1.0) / 2.0;
  496.  
  497.                 if (GlblDistRndrModel == AISO_DIST_PHONG_SPEC) {
  498.                 /* Add specular term, if have one. */
  499.                 if (DOT_PROD(N1, GlblLightSource) > 0.0) {
  500.                     PT_COPY(RefDir, N1);
  501.                     PT_SCALE(RefDir, 2 * Z);
  502.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  503.                     Z1 += pow(fabs(RefDir[2]),
  504.                           GlblCosinePower);
  505.                 }
  506.  
  507.                 if (DOT_PROD(N2, GlblLightSource) > 0.0) {
  508.                     PT_COPY(RefDir, N2);
  509.                     PT_SCALE(RefDir, 2 * Z);
  510.                     PT_SUB(RefDir, RefDir, GlblLightSource);
  511.                     Z2 += pow(fabs(RefDir[2]),
  512.                           GlblCosinePower);
  513.                 }
  514.                 }
  515.             }
  516.  
  517.             Z1 = pow(Z1, GlblShaderPower);
  518.             Z2 = pow(Z2, GlblShaderPower);
  519.     
  520.             Points1[i] = Z1 + 1.0 / NORMAL_ANGLE_SCALE;
  521.             Points2[i] = Z2 + 1.0 / NORMAL_ANGLE_SCALE;
  522.             }
  523.             else {
  524.             if (GlblDistRndrModel == AISO_DIST_PHONG_2L ||
  525.                 GlblDistRndrModel == AISO_DIST_PHONG_2L_SPEC) {
  526.                 if (DOT_PROD(N1, N2) > 0.0) {
  527.                 Z = (DOT_PROD(N1, GlblLightSource) +
  528.                      DOT_PROD(N2, GlblLightSource)) / 2.0;
  529.                 Z = fabs(Z);
  530.  
  531.                 if (GlblDistRndrModel == AISO_DIST_PHONG_2L_SPEC) {
  532.                     PT_BLEND(RefDir, N1, N2, 0.5);
  533.                     PT_NORMALIZE(RefDir);
  534.             
  535.                     /* Add specular term, if have one. */
  536.                     if (DOT_PROD(RefDir,
  537.                          GlblLightSource) > 0.0) {
  538.                     PT_SCALE(RefDir, 2 * Z);
  539.                     PT_SUB(RefDir, RefDir,
  540.                            GlblLightSource);
  541.                     Z += pow(fabs(RefDir[2]),
  542.                          GlblCosinePower);
  543.                     }
  544.                     else {
  545.                     PT_SCALE(RefDir, -2 * Z);
  546.                     PT_SUB(RefDir, RefDir,
  547.                            GlblLightSource);
  548.                     Z += pow(fabs(RefDir[2]),
  549.                          GlblCosinePower);
  550.                     }
  551.                 }
  552.                 }
  553.                 else
  554.                   Z = 1.0;
  555.             }
  556.             else { /* AISO_DIST_PHONG || AISO_DIST_PHONG_SPEC */
  557.                 if (DOT_PROD(N1, N2) > 0.0) {
  558.                 Z = (DOT_PROD(N1, GlblLightSource) +
  559.                      DOT_PROD(N2, GlblLightSource)) / 2.0;
  560.                 Z = (Z + 1.0) / 2.0;
  561.  
  562.                 if (GlblDistRndrModel == AISO_DIST_PHONG_SPEC) {
  563.                     PT_BLEND(RefDir, N1, N2, 0.5);
  564.                     PT_NORMALIZE(RefDir);
  565.             
  566.                     /* Add specular term, if have one. */
  567.                     if (DOT_PROD(RefDir,
  568.                          GlblLightSource) > 0.0) {
  569.                     PT_SCALE(RefDir, 2 * Z);
  570.                     PT_SUB(RefDir, RefDir,
  571.                            GlblLightSource);
  572.                     Z += pow(fabs(RefDir[2]),
  573.                          GlblCosinePower);
  574.                     }
  575.                 }
  576.                 }
  577.                 else
  578.                   Z = 1.0;
  579.             }
  580.  
  581.             Z = pow(Z, GlblShaderPower);
  582.  
  583.             Points[i] *= Z + 1.0 / NORMAL_ANGLE_SCALE;
  584.             }
  585.         }
  586.             break;
  587.         case AISO_DIST_ZNORMAL:
  588.         for (i = 0; i < DistCrv2 -> Length; i++) {
  589.             CagdVType N1, N2, RefDir;
  590.             CagdRType *R, Z, Z1, Z2,
  591.                 t1 = BOUND(Nodes[i], TMin1, TMax1),
  592.                 t2 = BOUND(Nodes[i], TMin2, TMax2);
  593.  
  594.             R = CagdCrvEval(NCrv1, t1);
  595.             CagdCoerceToE3(N1, &R, -1, NCrv1 -> PType);
  596.             R = CagdCrvEval(NCrv2, t2);
  597.             CagdCoerceToE3(N2, &R, -1, NCrv2 -> PType);
  598.  
  599.             PT_NORMALIZE(N1);
  600.             PT_NORMALIZE(N2);
  601.  
  602.             if (GlblVariableWidth) {
  603.             Z1 = 1.0 + GlblCosinePower - fabs(N1[2]),
  604.             Z2 = 1.0 + GlblCosinePower - fabs(N2[2]);
  605.  
  606.             Z1 = pow(Z1, GlblShaderPower);
  607.             Z2 = pow(Z2, GlblShaderPower);
  608.  
  609.             Points1[i] = Z1;
  610.             Points2[i] = Z2;
  611.             }
  612.             else {
  613.             Z = 1.0 + GlblCosinePower -
  614.                                (fabs(N1[2]) + fabs(N2[2])) / 2.0;
  615.  
  616.             Z = pow(Z, GlblShaderPower);
  617.  
  618.             Points[i] *= Z;
  619.             }
  620.         }
  621.             break;
  622.         case AISO_DIST_POINT_E3:
  623.         for (i = 0; i < DistCrv2 -> Length; i++) {
  624.             CagdVType P1, P2;
  625.             CagdRType *R, Z, Z1, Z2,
  626.                 t1 = BOUND(Nodes[i], TMin1, TMax1),
  627.                 t2 = BOUND(Nodes[i], TMin2, TMax2);
  628.  
  629.             R = CagdCrvEval(Crv1, t1);
  630.             CagdCoerceToE3(P1, &R, -1, NCrv1 -> PType);
  631.             R = CagdCrvEval(Crv2, t2);
  632.             CagdCoerceToE3(P2, &R, -1, NCrv2 -> PType);
  633.  
  634.             if (GlblVariableWidth) {
  635.             Z1 = CGDistPointPoint(P1, GlblLightSource);
  636.             Z2 = CGDistPointPoint(P2, GlblLightSource);
  637.  
  638.             Z1 = pow(Z1, GlblShaderPower);
  639.             Z2 = pow(Z2, GlblShaderPower);
  640.  
  641.             Points1[i] = 1 / (Z1 + GlblCosinePower);
  642.             Points2[i] = 1 / (Z2 + GlblCosinePower);
  643.             }
  644.             else {
  645.             PT_BLEND(P1, P1, P2, 0.5);
  646.             Z = CGDistPointPoint(P1, GlblLightSource);
  647.  
  648.             Z = pow(Z, GlblShaderPower);
  649.  
  650.             Points[i] *= 1 / (Z + GlblCosinePower);
  651.             }
  652.         }
  653.             break;
  654.         default:
  655.         break;
  656.     }
  657.  
  658.     IritFree((VoidPtr) Nodes);
  659.  
  660.     if (GlblRandomDist > 0.0) {
  661.         CagdRType
  662.         *Points = DistCrv2 -> Points[1];
  663.  
  664.         for (i = 0; i < DistCrv2 -> Length; i++)
  665.         Points[i] *= IritRandom(1 / GlblRandomDist,
  666.                     GlblRandomDist);
  667.  
  668.         if (GlblVariableWidth) {
  669.         CagdRType
  670.             *Points1 = DistCrv2Aux1 -> Points[1],
  671.             *Points2 = DistCrv2Aux2 -> Points[1];
  672.  
  673.         for (i = 0; i < DistCrv2 -> Length; i++) {
  674.             Points1[i] *= IritRandom(1 / GlblRandomDist,
  675.                          GlblRandomDist);
  676.             Points2[i] *= IritRandom(1 / GlblRandomDist,
  677.                          GlblRandomDist);
  678.         }
  679.         }
  680.     }
  681.     }
  682.  
  683.     if (GlblVariableWidth) {
  684.     AttrSetObjAttrib(&Crv1 -> Attr, "VarWidth",
  685.              GenCRVObject(DistCrv2Aux1), FALSE);
  686.     AttrSetObjAttrib(&Crv2 -> Attr, "VarWidth",
  687.              GenCRVObject(DistCrv2Aux2), FALSE);
  688.     }
  689.  
  690.     return DistCrv2;
  691. }
  692.  
  693. /*****************************************************************************
  694. * DESCRIPTION:                                                               *
  695. *   Approximates t to the power of Power, as powers of twos only.            *
  696. *                                                                            *
  697. * PARAMETERS:                                                                *
  698. *   t:         To raise to the power of Power.                               *
  699. *   Power:     If Power is of the form 2^n, n integer, result is exact.      *
  700. *                                                                            *
  701. * RETURN VALUE:                                                              *
  702. *   RealType:  t^Power                                                       *
  703. *****************************************************************************/
  704. static RealType IntPower2(RealType t, int Power)
  705. {
  706.     int i;
  707.  
  708.     if (Power == 0)
  709.         return 1.0;
  710.  
  711.     for (i = 1; i < Power; i <<= 1)
  712.     t *= t;
  713.  
  714.     return t;
  715. }
  716.  
  717. /*****************************************************************************
  718. * DESCRIPTION:                                                               M
  719. * AIsoShad Exit routine.                             M
  720. *                                                                            *
  721. * PARAMETERS:                                                                M
  722. *   ExitCode:    To notify O.S. with result of program.                      M
  723. *                                                                            *
  724. * RETURN VALUE:                                                              M
  725. *   void                                                                     M
  726. *                                                                            *
  727. * KEYWORDS:                                                                  M
  728. *   AIsoShaderExit                                                           M
  729. *****************************************************************************/
  730. static void AIsoShaderExit(int ExitCode)
  731. {
  732.     exit(ExitCode);
  733. }
  734.  
  735. #ifdef DEBUG
  736.  
  737. /*****************************************************************************
  738. * DESCRIPTION:                                                               *
  739. *    Dummy function to link at debugging time.                               *
  740. *                                                                            *
  741. * PARAMETERS:                                                                *
  742. *                                                                            *
  743. * RETURN VALUE:                                                              *
  744. *   void                                                                     *
  745. *                                                                            *
  746. * KEYWORDS:                                                                  *
  747. *****************************************************************************/
  748. void DummyLinkCagdDebug(void)
  749. {
  750.     IritPrsrDbg();
  751. }
  752.  
  753. #endif /* DEBUG */
  754.